<?php

class Module_Impl_Auth implements Module_Interface_Auth {
	
	const SESSION_NAME = 'my_blog_auth';	
	
	const FAIL_LOGIN_BECAUSE_USER_NO_EXIST = 'auth.login.fail.user.no.exist';
	const FAIL_LOGIN_BECAUSE_PASSWORD_WRONG = 'auth.login.fail.password.wrong';	

	private $_check_auth_by = 'username';
	
	/**
   * Singleton instance
   * @var Module_Impl_Auth
   */
	private static $_instance = null;
	/**
	 * @var Module_Interface_Select
	 */
	private $_interface_user_select = null;
	/**
	 * @var Module_Interface_Opration
	 */
	private $_interface_user_opration = null;
	
	/**
	 * @var Module_Interface_Translate
	 */
	protected $_interface_translate = null;
	
	protected function __construct(){	
		$this->_interface_translate = Module_Impl_I18n::getInstance();
		$this->_interface_user_select = Module_Impl_User_Select::getInstance();
		$this->_interface_user_opration = Module_Impl_User_Opration::getInstance();
	}
	/**
     * Singleton instance 
     * @return Module_Impl_Auth
     */
	public static function getInstance(){
		if (null === self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	public function getCheckAuthBy(){
		return $this->_check_auth_by;
	}
	
	public function setCheckAuthBy($field){
		$this->_check_auth_by = $field;
	}
	
	/**
		 * 验证某用户 连接数据库
		 * @param string $name
		 * @param string $password
		 * @param int $type
		 * @param bool $isMd5
		 * @throws Exception
		 * @return Object_User
		*/
	public function checkAuth($name,$password,$isMd5 = false){
		try{					
			$user = $this->_interface_user_select->getByField($this->_check_auth_by,$name);					
			$result = ($this->_equalPassword($user,$password,$isMd5))?$user:false;	
		}catch(Exception $e){
			throw $e;
		}
		return $result;
	}	
	/**
		 * 
		 * @param int $userid
		 * @param string $password
		 * @param bool $isMd5
		 * @throws Exception
		 * @return Object_User
		*/
	public function checkAuthId($userid,$password,$isMd5 = true){
		try{			
			$user = $this->_interface_user_select->getById($userid);			
			$result = ($this->_equalPassword($user,$password,$isMd5))?$user:false;
		}catch(Exception $e){
			throw $e;
		}
		return $result;
	}
	/**
		 * 设置session
		 * @param array $data
		 * @param int $type
		 * @throws Exception
		 * @return 
		*/
	public function setSession($data,$isRecordLoginTime = false){
		if(empty($data)){
			throw new Exception('Param is wrong');
		}
		if($data instanceof Object_Abstract ){
			$data = $data->getInfo();
		}
		if(is_array($data)){			
			$_data['id'] = $data['id'];
			$_data['password'] = md5($data['password']);			
			$_SESSION[self::SESSION_NAME] = $_data;
			if($isRecordLoginTime){				
				$this->_interface_user_opration->update($_data['id'],array('login_at'=>Util_TimeMath::getDateTime()));
			}	
			return true;
		}else{
			throw new Exception('Param must be a array or Object');
		}
	}
	/**
		 * 清除session
		 * @param int $type
		 * @throws Exception
		 * @return bool
		*/
	public function clearSession($isRecordLogoutTime = false){		
		if(isset($_SESSION[self::SESSION_NAME])){
			if($isRecordLogoutTime){
				$id = isset($_SESSION[self::SESSION_NAME]['id'])?$_SESSION[self::SESSION_NAME]['id']:null;
				if(!empty($id)){
					$this->_interface_user_opration->update($id,array('logout_at'=>Util_TimeMath::getDateTime()));
				}
			}
			unset($_SESSION[self::SESSION_NAME]);
		}
		return true;
	}
	/**
		 * 从session中判断，某类型用户是否登陆 验证数据库
		 * @param int $type
		 * @throws Exception
		 * @return Object_User
		*/
	public function isLogin(){	
		try{				
			if(isset($_SESSION[self::SESSION_NAME])){
				$stdClass = $_SESSION[self::SESSION_NAME];
				if($stdClass instanceof Object_Abstract ){
					return $stdClass;
				}
				if(is_array($stdClass)){
					$_userid = (int)$stdClass['id'];
					$_password = $stdClass['password'];
					if(!empty($_userid)){
						return $this->checkAuthId($_userid,$_password);					
					}
				}
			}
		}catch(Exception $e){
			throw $e;
		}
		return null;
	}
	
	/**
		 * 
		 * @param mix $user
		 * @param string $password2
		 * @param bool $isMd5
		 * @return bool
		*/
	private function _equalPassword($user,$password2,$isMd5 = false){		
		if(empty($user)){
			$this->_interface_translate->clearErrorMsg();
			$this->_interface_translate->setErrorMsg('username',self::FAIL_LOGIN_BECAUSE_USER_NO_EXIST);
			return false;
		}		
		if(!$user instanceof Object_User ){
			$this->_interface_translate->clearErrorMsg();
			$this->_interface_translate->setErrorMsg('username',self::FAIL_LOGIN_BECAUSE_USER_NO_EXIST);
			return false;
		}		
		$password1 = $user->password;
		$password1 = $isMd5?md5($password1):$password1;
		if($password1 === $password2){
			return true;
		}
		$this->_interface_translate->clearErrorMsg();
		$this->_interface_translate->setErrorMsg('password',self::FAIL_LOGIN_BECAUSE_PASSWORD_WRONG);
		return false;
	}	
}